package com.lvmama.dashboard.rop.service.ssh;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import com.lvmama.dashboard.core.annotation.AjaxMethod;
import com.lvmama.dashboard.core.ssh.RmtShellRunner;
import com.lvmama.dashboard.entity.ShellExec;
import com.lvmama.dashboard.entity.ShellTask;
import com.lvmama.dashboard.exception.ServiceException;
import com.lvmama.dashboard.model.rop.AjaxRequestBody;
import com.lvmama.dashboard.model.rop.AjaxResponse;
import com.lvmama.dashboard.model.rop.ssh.request.GetExecListRequest;
import com.lvmama.dashboard.model.rop.ssh.request.SubmitSyncLogRequest;
import com.lvmama.dashboard.model.rop.ssh.request.SyncLogGetExecLogRequest;
import com.lvmama.dashboard.model.rop.ssh.response.GetExecListResponse;
import com.lvmama.dashboard.model.rop.ssh.response.SubmitSyncLogResponse;
import com.lvmama.dashboard.model.rop.ssh.response.SyncLogGetExecLogResponse;
import com.lvmama.dashboard.service.ajax.ssh.IRmtShellExecService;
import com.lvmama.dashboard.service.ssh.IShellExecService;
import com.lvmama.dashboard.service.ssh.IShellTaskService;
import com.lvmama.dashboard.utils.ErrDict;
import com.lvmama.java.rhino.spark.utils.Constants;
import com.lvmama.rhino.utils.JedisClusterUtils;

@Component("rmtShellExecService")
public class RmtShellExecServiceImpl implements IRmtShellExecService {
	private static final String DEFAULT_CHARSET = Charset.defaultCharset().toString();
	private static final String TASK_NAME = "sync-log-from-hdfs-to-elastic";
	@Autowired
	@Qualifier("shellExecThreadPool")
	private ThreadPoolTaskExecutor shellExecThreadPool;
	@Autowired
	private IShellExecService shellExecService;
	@Autowired
	private IShellTaskService shellTaskService;
	@Override
	@AjaxMethod(ajaxmethod = "com.lvtu.dashboard.ssh.submitSyncLogJob")
	public AjaxResponse<SubmitSyncLogResponse> submitSyncLogJob(AjaxRequestBody<SubmitSyncLogRequest> requestBody) {
		SubmitSyncLogRequest request = requestBody.getT();
		String startTimeStr = request.getStartTime();
		String endTimeStr = request.getEndTime();
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date startTime = null;
		Date endTime = null;
		AjaxResponse<SubmitSyncLogResponse> responseBody = new AjaxResponse<SubmitSyncLogResponse>();
		try {
			startTime = format.parse(startTimeStr);
			endTime = format.parse(endTimeStr);
		} catch (ParseException e) {
			responseBody.setCode(Constants.CODE.ERROR.getCode());
			responseBody.setMessage(ErrDict.DATA_ERR.DATA_FORMAT_ERR.getMsg());
			return responseBody;
		}
		if(endTime.before(startTime)) {
			responseBody.setCode(Constants.CODE.ERROR.getCode());
			responseBody.setMessage(ErrDict.DATA_ERR.END_BEFORE_START.getMsg());
			return responseBody;
		}
		Calendar cal = Calendar.getInstance();
		cal.setTime(endTime);
		cal.add(Calendar.HOUR_OF_DAY, -5);
		if(cal.getTime().after(startTime)) {
			responseBody.setCode(Constants.CODE.ERROR.getCode());
			responseBody.setMessage(ErrDict.DATA_ERR.END_AFTER_BEYOND.getMsg());
			return responseBody;
		}
		ShellTask shellTask = shellTaskService.queryByTashName(TASK_NAME);
		Map<String, String> param = new HashMap<String, String>();
		param.put("startTime", startTimeStr);
		param.put("endTime", endTimeStr);
		Map<String, Object> shellQueue = JedisClusterUtils.getInstance().hmget("shell_queue");
		String uuid = UUID.randomUUID().toString();
		RmtShellRunner runner = new RmtShellRunner(uuid, shellTask.getShellName(), param);
		shellQueue.put(uuid, runner);
		JedisClusterUtils.getInstance().hmset("shell_queue", shellQueue);
		shellExecThreadPool.execute(runner);
		return new AjaxResponse<SubmitSyncLogResponse>();
	}

	@Override
	@AjaxMethod(ajaxmethod = "com.lvtu.dashboard.ssh.getLog")
	public AjaxResponse<SyncLogGetExecLogResponse> getLog(AjaxRequestBody<SyncLogGetExecLogRequest> requestBody) {
		SyncLogGetExecLogRequest request = requestBody.getT();
		ShellExec shellExec = shellExecService.queryByExecId(request.getExecId());
		String status = shellExec.getStatus();
		
		AjaxResponse<SyncLogGetExecLogResponse> responseBody = new AjaxResponse<SyncLogGetExecLogResponse>();
		SyncLogGetExecLogResponse response = new SyncLogGetExecLogResponse();
		responseBody.setData(response);
		if(Constants.SHELL_STATUS.RUNNING.getCode().equals(status)) {
			long lastLine = request.getLastLine();
			List<String> logList = JedisClusterUtils.getInstance().lget("SHELL_EXEC_LOG_" + shellExec.getExecId(), lastLine);
			response.setLogList(logList);
			response.setLastLine(lastLine + logList.size());
			response.setActive(true);
			return responseBody;
		}
		
		String logDirStr = Constants.getInstance().getValue("remote.shell.current.log.dir");
		String fileName = shellExec.getShellOutFile().getFileName();
		File logFile = new File(logDirStr + fileName);
		if(!logFile.exists()) {
			throw new ServiceException(ErrDict.SHELL.LOG_FILE_NOT_EXIST.getMsg());
		}
		List<String> logList = new ArrayList<String>();
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new InputStreamReader(new FileInputStream(logFile), DEFAULT_CHARSET));
			String lineStr = reader.readLine();
			while(lineStr != null) {
				logList.add(lineStr + "<br>");
				lineStr = reader.readLine();
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(reader != null) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		response.setLogList(logList);
		response.setActive(false);
		return responseBody;
	}

	@SuppressWarnings("unchecked")
	@Override
	@AjaxMethod(ajaxmethod = "com.lvtu.dashboard.ssh.getTaskList")
	public AjaxResponse<GetExecListResponse> getExecList(AjaxRequestBody<GetExecListRequest> requestBody) {
		GetExecListRequest request = requestBody.getT();
		String taskName = request.getTaskName();
		Map<String, List<?>> result = shellExecService.queryByTaskName(taskName);
		AjaxResponse<GetExecListResponse> responseBody = new AjaxResponse<GetExecListResponse>();
		GetExecListResponse response = new GetExecListResponse();
		responseBody.setData(response);
		response.setExecIdList((List<Integer>)result.get("execIdList"));
		response.setWaitShellList((List<String>)result.get("waitShellList"));
		return responseBody;
	}

}
